package com.lhy.framework.context.annotation;

import cn.hutool.core.util.StrUtil;
import com.lhy.framework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import com.lhy.framework.beans.factory.factory.BeanDefinition;
import com.lhy.framework.beans.factory.support.BeanDefinitionRegistry;
import com.lhy.framework.stereotype.Component;

import java.util.Set;

/**
 * @Title:
 * @Description: 功能概述:
 * @Author: lihaiyang
 * @version: 1.0 .
 * @Date: 2022-09-14 10:48
 * @Copyright: Copyright(c)2022 RedaFlight.comAll Rights Reserved
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    private final BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidates) {
                // 解析 Bean的作用域singleton、prototype
                String beanScope = resolveBeanScope(beanDefinition);
                if (StrUtil.isNotBlank(beanScope)) {
                    beanDefinition.setScope(beanScope);
                }
                registry.registerBeanDefinition(determineBeanName(beanDefinition), beanDefinition);
            }
        }

        // 注册处理注解的BeanPostProcessor （@Autowired、@Value）
        registry.registerBeanDefinition("com.lhy.springframework.context.annotation.internalAutowiredAnnotationProcessor",new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
    }

    /**
     * 解析BeanName
     * @param beanDefinition
     * @return
     */
    private String determineBeanName(BeanDefinition beanDefinition) {
        Class<?> clazz = beanDefinition.getClazz();
        Component component = clazz.getAnnotation(Component.class);
        String value = component.value();
        if (StrUtil.isEmpty(value)) {
            value = StrUtil.lowerFirst(clazz.getSimpleName());
        }
        return value;
    }

    private String resolveBeanScope(BeanDefinition beanDefinition) {
        Class<?> clazz = beanDefinition.getClazz();
        Scope scope = clazz.getAnnotation(Scope.class);
        if (null != scope) {
            return scope.value();
        }
        return StrUtil.EMPTY;
    }
}
